var getSECCurveByName = require("./ecdh/sec.js")
var ec = require("./ecdh/ec.js")
var ECCurveFp = ec.ECCurveFp
var ECPointFp = ec.ECPointFp
var SecureRandom = require("./ecdh/rng.js")
var jsbn2 = require("./ecdh/jsbn2.js")
var BigInteger = jsbn2.BigInteger

class ECDH {

  pick_rand() {
    var n = ECDH.prototype.n;
    var n1 = n.subtract(BigInteger.ONE);
    var r = new BigInteger(n.bitLength(), ECDH.prototype.rng);
    return r.mod(n1).add(BigInteger.ONE);
  }
  get_curve() {
    return new ECCurveFp(ECDH.prototype.q, ECDH.prototype.a, ECDH.prototype.b);
  }
  get_G(curve) {
    return new ECPointFp(curve, curve.fromBigInteger(ECDH.prototype.gx), curve.fromBigInteger(ECDH.prototype.gy));
  }
  get_pub(privateKey) {
    var curve = ECDH.prototype.get_curve();
    var G = ECDH.prototype.get_G(curve);
    var P = G.multiply(privateKey);
    return [P.getX().toBigInteger(), P.getY().toBigInteger()];
  }
  generateKeys() {
    var privateKey = ECDH.prototype.pick_rand();
    var [publicKeyX, publicKeyY] = ECDH.prototype.get_pub(privateKey);
    return [privateKey, publicKeyX, publicKeyY];
  }
  secret_key(privateKey,publicKeyX, publicKeyY) {
    var curve = ECDH.prototype.get_curve();
    var P = new ECPointFp(curve, 
    curve.fromBigInteger(new BigInteger(publicKeyX,16)), 
    curve.fromBigInteger(new BigInteger(publicKeyY,16)));
    var S = P.multiply(privateKey);
    return [S.getX().toBigInteger(), S.getY().toBigInteger()];
  }
}
ECDH.prototype.SECCurve = new getSECCurveByName("secp256r1");
ECDH.prototype.curve = ECDH.prototype.SECCurve.getCurve();
ECDH.prototype.g = ECDH.prototype.SECCurve.getG();
ECDH.prototype.rng = new SecureRandom();

ECDH.prototype.q = ECDH.prototype.curve.getQ();
ECDH.prototype.a = ECDH.prototype.curve.getA().toBigInteger();
ECDH.prototype.b = ECDH.prototype.curve.getB().toBigInteger();
ECDH.prototype.gx = ECDH.prototype.g.getX().toBigInteger();
ECDH.prototype.gy = ECDH.prototype.g.getY().toBigInteger();
ECDH.prototype.n = ECDH.prototype.SECCurve.getN();

module.exports = ECDH;